package com.ym.utils.cmcmfileuploadutils;

import com.ym.utils.exception.CustomException;
import net.coobird.thumbnailator.Thumbnails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.List;
import java.util.*;

@Component
public class OSSFileUpload {

    private final static Logger log = LoggerFactory.getLogger(OSSFileUpload.class);

    //@Value("${file.urlpPath}")
    private String urlPath;

    // @Value("${file.address}")
    private String address;

    /**
     * 宽高比例压缩
     *
     * @param file
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> uploadImg2Oss1(MultipartFile file, Float widthPX) throws CustomException {
        if (file.isEmpty()) {
            throw new CustomException(500, "文件为空");
        }
        if (file.getSize() > 10 * 1024 * 1024) {
            throw new CustomException(500, "上传图片大小不能超过10M！");
        }
        String strFix = ".jpeg.bmp.gif.jpg.psd.dxf.png";
        String originalFilename = file.getOriginalFilename();
        String substring = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();
        if (strFix.contains(substring) == false) {
            throw new CustomException(500, "请确认文件格式");
        }
        String name = new Random().nextInt(10000) + System.currentTimeMillis() + substring;
        InputStream inputStream = null;
        FileOutputStream downloadFile = null;
        Map<String, Object> map = new HashMap<>();
        try {
            inputStream = file.getInputStream();
            // 把图片读入到内存中
            Image imageTookit = Toolkit.getDefaultToolkit().createImage(toByteArray(inputStream));
            BufferedImage bufImg = toBufferedImage(imageTookit);
            // 压缩代码
            //设置初始化的压缩率为1
            float ratio = 1f;
            //设置压缩后的图片宽度
            float width = 54f;
            if (ObjectUtils.isEmpty(widthPX) == false) {
                width = widthPX;
            }
            //获取原图片的宽度、高度
            float ImgWith = bufImg.getWidth();
            float ImgHight = bufImg.getHeight();
            //根据原始图片宽度，与压缩图宽度重新计算压缩率
            if (ImgWith > width) {
                ratio = width / ImgWith;
            }
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            //按压缩率进行压缩
            bufImg = Thumbnails.of(bufImg).scale(ratio).asBufferedImage();
            //防止图片变红
            // BufferedImage newBufferedImage = new BufferedImage(bufImg.getWidth(), bufImg.getHeight(), BufferedImage.TYPE_INT_RGB);
            // newBufferedImage.createGraphics().drawImage(bufImg, 0, 0, Color.WHITE, null);
            //先转成jpg格式来压缩,然后在通过OSS来修改成源文件本来的后缀格式
            ImageIO.write(bufImg, "jpg", bos);
            //获取输出流
            inputStream = new ByteArrayInputStream(bos.toByteArray());
            int index;
            byte[] bytes = new byte[1024];
            makeExits(urlPath);
            String filePath = urlPath + name;
            String fielURL = address + name;
            downloadFile = new FileOutputStream(filePath);
            while ((index = inputStream.read(bytes)) != -1) {
                downloadFile.write(bytes, 0, index);
                downloadFile.flush();
            }

            //System.out.println("文件名称="+name);
            //上传OSS
            //this.uploadFile2OSS(inputStream, name);
            map.put("fileName", name);
            map.put("filePath", fielURL);
            return map;
        } catch (Exception e) {
            log.error("上传文件发生异常" + e.getMessage());
            throw new CustomException(500, "图片上传失败");
        } finally {
            try {
                if (downloadFile != null) {
                    downloadFile.flush();
                    downloadFile.close();
                }
            } catch (IOException e) {
                log.error("FileOutputStream 流关闭发生异常" + e.getMessage());
            }
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                log.error("InputStream 流关闭发生异常" + e.getMessage());
            }
        }
    }


    /**
     * 针对图片的质量压缩针对图片的质量压缩
     *
     * @param file
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> uploadImg2Oss(MultipartFile file) throws CustomException {
        if (file.isEmpty()) {
            throw new CustomException(500, "文件为空");
        }
        if (file.getSize() > 10 * 1024 * 1024) {
            throw new CustomException(500, "上传图片大小不能超过10M！");
        }
        String strFix = ".jpeg.bmp.gif.jpg.psd.dxf.png";

        String originalFilename = file.getOriginalFilename();
        String substring = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();
        if (strFix.contains(substring) == false) {
            throw new CustomException(500, "请确认文件格式");
        }
        Random random = new Random();
        String name = random.nextInt(10000) + System.currentTimeMillis() + substring;
        InputStream inputStream = null;
        FileOutputStream downloadFile = null;
        Map<String, Object> map = new HashMap<>();
        try {
            inputStream = file.getInputStream();

            // 把图片读入到内存中
            //BufferedImage bufImg = ImageIO.read(inputStream);
            Image imageTookit = Toolkit.getDefaultToolkit().createImage(toByteArray(inputStream));
            BufferedImage bufImg = toBufferedImage(imageTookit);
            // 压缩代码
            // 存储图片文件byte数组
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            //防止图片变红
            // BufferedImage newBufferedImage = new BufferedImage(bufImg.getWidth(), bufImg.getHeight(), BufferedImage.TYPE_INT_RGB);
            // newBufferedImage.createGraphics().drawImage(bufImg, 0, 0, Color.WHITE, null);
            //先转成jpg格式来压缩,然后在通过OSS来修改成源文件本来的后缀格式
            ImageIO.write(bufImg, "jpg", bos);
            //获取输出流
            inputStream = new ByteArrayInputStream(bos.toByteArray());
            int index;
            byte[] bytes = new byte[1024];
            makeExits(urlPath);
            String filePath = urlPath + name;
            String fielURL = address + name;
            downloadFile = new FileOutputStream(filePath);
            while ((index = inputStream.read(bytes)) != -1) {
                downloadFile.write(bytes, 0, index);
                downloadFile.flush();
            }
            map.put("fileName", name);
            map.put("filePath", fielURL);
            return map;
        } catch (Exception e) {
            log.error("上传文件发生异常" + e.getMessage());
            throw new CustomException(500, "图片上传失败");
        } finally {
            try {
                if (downloadFile != null) {
                    downloadFile.flush();
                    downloadFile.close();
                }
            } catch (IOException e) {
                log.error("FileOutputStream 流关闭发生异常" + e.getMessage());
            }
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                log.error("InputStream 流关闭发生异常" + e.getMessage());
            }
        }
    }


    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> uploadFile3Oss(MultipartFile file) throws CustomException {
        if (file.isEmpty()) {
            throw new CustomException(500, "文件为空");
        }
        if (file.getSize() > 200 * 1024 * 1024) {
            throw new CustomException(500, "上传文件大小不能超过200M");
        }

        String originalFilename = file.getOriginalFilename();
        String substring = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();

        Random random = new Random();
        String name = random.nextInt(10000) + System.currentTimeMillis() + substring;
        BufferedOutputStream stream = null;
        Map<String, Object> map = new HashMap<>();
        try {
            makeExits(urlPath);
            String filePath = urlPath + name;
            String fielURL = address + name;
            byte[] bytes = file.getBytes();
            stream = new BufferedOutputStream(new FileOutputStream(new File(filePath)));
            stream.write(bytes);
            stream.close();
           /* File dest = new File(filePath);
            //文件写入 注：需绝对路径标识
            file.transferTo(dest);*/
            map.put("fileName", name);
            map.put("filePath", fielURL);
            return map;
        } catch (Exception e) {
            log.error("上传文件失败" + e.getMessage());
            throw new CustomException(500, "上传文件失败");
        } finally {
            try {
                if (stream != null) {
                    stream.flush();
                    stream.close();
                }
            } catch (IOException e) {
                log.error("FileOutputStream 流关闭发生异常" + e.getMessage());
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public List<Map<String, Object>> uploadImg4Oss(MultipartFile[] files) throws CustomException {
        if (files.length > 0) {
            throw new CustomException(500, "文件为空");
        }
        List<Map<String, Object>> list = new ArrayList<>();
        MultipartFile file = null;
        BufferedOutputStream stream = null;

        for (int i = 0; i < files.length; i++) {
            file = files[i];

            String originalFilename = file.getOriginalFilename();
            String substring = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();
            Random random = new Random();
            String name = random.nextInt(10000) + System.currentTimeMillis() + substring;
            makeExits(urlPath);
            String filePath = urlPath + name;
            String fielURL = address + name;
            if (file.isEmpty() == false) {
                try {
                    byte[] bytes = file.getBytes();
                    stream = new BufferedOutputStream(new FileOutputStream(new File(filePath)));
                    stream.write(bytes);
                    stream.close();
                } catch (Exception e) {
                    log.error("上传文件失败" + e.getMessage());
                    throw new CustomException(500, "上传文件失败");
                } finally {
                    try {
                        if (stream != null) {
                            stream.flush();
                            stream.close();
                        }
                    } catch (IOException e) {
                        log.error("FileOutputStream 流关闭发生异常" + e.getMessage());
                    }
                }
            }
            Map<String, Object> map = new HashMap<>();
            map.put("fileName", name);
            map.put("filePath", fielURL);
            list.add(map);
        }
        return list;
    }


    @Transactional(rollbackFor = Exception.class)
    public String downLoadFileOss(String fileName, HttpServletResponse response) throws CustomException {
        if (ObjectUtils.isEmpty(fileName)) {
            throw new CustomException(500, "文件为空");
        }

        File file = new File(address + fileName);
        response.setContentType("multipart/form-data");
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
        byte[] buffer = new byte[1024];
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        try {
            fis = new FileInputStream(file);
            bis = new BufferedInputStream(fis);
            OutputStream os = response.getOutputStream();
            int i = bis.read(buffer);
            while (i != -1) {
                os.write(buffer, 0, i);
                i = bis.read(buffer);
            }
            return "success";
        } catch (Exception e) {
            log.error("文件下载失败" + e.getMessage());
        } finally {
            try {
                if (bis != null) {
                    bis.close();
                }
            } catch (IOException e) {
                log.error("BufferedInputStream 流关闭发生异常" + e.getMessage());
            }
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                log.error("FileInputStream 流关闭发生异常" + e.getMessage());
            }
        }
        return "false";
    }


    public static BufferedImage toBufferedImage(Image image) {
        if (image instanceof BufferedImage) {
            return (BufferedImage) image;
        }
        // This code ensures that all the pixels in the image are loaded
        image = new ImageIcon(image).getImage();
        BufferedImage bimage = null;
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        try {
            int transparency = Transparency.OPAQUE;
            GraphicsDevice gs = ge.getDefaultScreenDevice();
            GraphicsConfiguration gc = gs.getDefaultConfiguration();
            bimage = gc.createCompatibleImage(image.getWidth(null), image.getHeight(null), transparency);
        } catch (HeadlessException e) {
            // The system does not have a screen
        }
        if (bimage == null) {
            // Create a buffered image using the default color model
            int type = BufferedImage.TYPE_INT_RGB;
            bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
        }
        // Copy image to buffered image
        Graphics g = bimage.createGraphics();
        // Paint the image onto the buffered image
        g.drawImage(image, 0, 0, null);
        g.dispose();
        return bimage;
    }

    private static byte[] toByteArray(InputStream input) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024 * 4];
        int n = 0;
        while (-1 != (n = input.read(buffer))) {
            output.write(buffer, 0, n);
        }
        return output.toByteArray();
    }

    public void makeExits(String urlPath) {
        File file = new File(urlPath);
        //如果文件夹不存在则创建
        if (!file.exists() && !file.isDirectory()) {
            file.mkdir();
        }
    }

}
